package com.shaoyu.spring.study.validate.core;

import org.springframework.aop.support.AopUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Desc :
 * @Author: shaoyu
 * @Date : 2022/8/23 10:12
 */

public class ValidateInterceptor {

    private final Object bean;

    private final Method method;

    private final Map<String,Class> methodParameterTypesMap;

    public ValidateInterceptor(Object bean, Method method) {
        this.bean = bean;
        this.method = method;
        Parameter[] parameters = method.getParameters();
        if(Objects.isNull(parameters) || parameters.length <=0 ){
            this.methodParameterTypesMap = Collections.EMPTY_MAP;
        }else{
            LocalVariableTableParameterNameDiscoverer discoverer =  new LocalVariableTableParameterNameDiscoverer();
            String[] parameterNames = discoverer.getParameterNames(this.method);
            this.methodParameterTypesMap = new HashMap<>();
            for (int i = 0; i < parameterNames.length; i++) {
                methodParameterTypesMap.put(parameterNames[i],parameters[i].getType());
            }
        }
    }
    public Object invoke(Object[] args) throws InvocationTargetException, IllegalAccessException {
        return method.invoke(bean,args);
    }
    public String getClassName(){
        return AopUtils.getTargetClass(bean).getName();
    }
    public Method getMethod(){
        return method;
    }

    public String getMethodName(){
        return method.getName();
    }

    public List<String> getArgNames(){
        return Stream.of(method.getParameters()).map(Parameter::getName).collect(Collectors.toList());
    }
    public List<Class> getArgTypes(){
        return Stream.of(method.getParameters()).map(Parameter::getType).collect(Collectors.toList());
    }
    public Map<String,Class> getArgTypesMap(){
        return this.methodParameterTypesMap;
    }
}
